﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;
using F1010DB.Entity;

namespace F1010DB.Common
{
    /// <summary>
    /// Class này dùng để kiểm tra security code
    /// </summary>
    public abstract class SecurityCodeCompare
    {
        private SecurityModel scModel = null;
        private BaseDatabase dbContext = null;
        
        
        private const string SECURITY_CODE = " SELECT A.MA_DON_VI, A.SECURITY_KEY,A.ACTIVE_FAIL, A.HIEU_LUC_LOCK,A.ISACTIVE FROM HDVNQTRI.DON_VI_MASTER_ACCOUNT A  " +
                                              " INNER JOIN HDVNQTRI.DON_VI_MASTER B ON B.MA_DON_VI = A.MA_DON_VI " +
                                              " WHERE A.MA_DON_VI = @madonvi AND A.DEL_F = '0' AND B.GIAI_TAN_DON_VI = '0' AND B.CAP_DON_VI = '3' AND B.TINH_TRANG_DON_VI = '1' ";
        private const string LOCK_DATE = " SELECT MA_DON_VI WHERE LOCK = '1' AND HIEU_LUC_LOCK <= GETDATE() AND MA_DON_VI = @madonvi";
        private const string RESET = "UPDATE LOCK = '0', ISACTIVE = '1', ACTIVE_FAIL = 0 WHERE MA_DON_VI = @madonvi";
        private const string UPDATE_SUCCESS = " UPDATE HDVNQTRI.DON_VI_MASTER_ACCOUNT SET ISACTIVE = '1',INS_DATE=GETDATE(), INS_USER='Admin', UPD_USER=@madonvi, UPD_DATE=GETDATE() WHERE MA_DON_VI = @madonvi";
        private const string UPDATE_FAIL = " UPDATE HDVNQTRI.DON_VI_MASTER_ACCOUNT SET ACTIVE_FAIL = ACTIVE_FAIL + 1 WHERE MA_DON_VI = @madonvi";
        private  const string UPDATE_LOCK = " UPDATE HDVNQTRI.DON_VI_MASTER_ACCOUNT SET ISACTIVE = '0', LOCK = '1', HIEU_LUC_LOCK = DATEADD(GETDATE(), 1) WHERE MA_DON_VI = @madonvi";
        private const string CHECK_ACTIVE = " SELECT ISACTIVE FROM HDVNQTRI.DON_VI_MASTER_ACCOUNT WHERE MA_DON_VI = @madonvi AND ISACTIVE = '1'";
        private const string GET_UNIT_INFORMATION = " SELECT MA_DON_VI, TEN_DON_VI, EMAIL, EMAIL_2, SO_DIEN_THOAI_DD, TRUONG_DAI_DIEN FROM HDVNQTRI.DON_VI_MASTER WHERE MA_DON_VI = @madonvi AND GIAI_TAN_DON_VI = '0' AND DEL_F = '0'";
        private const string CHECK_UNIT_EXIST_ACCOUNT = " SELECT COUNT(MA_DON_VI) FROM HDVNQTRI.DON_VI_MASTER_ACCOUNT WHERE MA_DON_VI = @madonvi AND ISACTIVE = '1' ";

        /// <summary>
        /// Mỗi khi đăng nhập phải trải qua check security code đã được kích hoạt
        /// </summary>
        /// <param name="scModel"></param>
        /// <returns></returns>
        protected bool checkActiveAccount(SecurityModel scModel)
        {
            dbContext = new BaseDatabase();

            Dictionary<string, object> ob = new Dictionary<string, object>();
            
            ob.Add("@madonvi", scModel.maDonVi);

            int countRow = Int16.Parse(dbContext.readATable(CHECK_UNIT_EXIST_ACCOUNT, CommandType.Text, ob).Rows[0][0].ToString());

            return countRow == 1;
           
        }

        /// <summary>
        /// Tiến hành mở khóa software
        /// </summary>
        /// <param name="securityModel"></param>
        /// <returns></returns>
        protected int activeSoftware(SecurityModel securityModel)
        {
            if (securityModel == null)
            {
                return -1;
            }

            scModel = securityModel;

            // Validate
            int isErrorInput = validateInput(scModel);

            if (isErrorInput != 0)
            {
                return isErrorInput;
            }

            Dictionary<string, object> objForm = new Dictionary<string,object>();
            objForm.Add("@madonvi", scModel.maDonVi);

            Dictionary<string, object> objSecurity = new Dictionary<string, object>();
            objSecurity.Add("@madonvi", scModel.maDonVi);
            objSecurity.Add("@securitycode", scModel.securityCode);

            dbContext = new BaseDatabase();

            DataView dviewResult = dbContext.readDataView(SECURITY_CODE, CommandType.Text, objForm);

            if (dviewResult.Count == 0)
            {
                return 0;
            }

            DataTable dt = dviewResult.ToTable();
            DataRow dr = dt.Rows[0];
            int isAccess = 1;
            string lockDate = dr["HIEU_LUC_LOCK"].ToString();

            if (scModel.securityCode.Equals(dr["SECURITY_KEY"].ToString()) == true)
            {
                int iActiveFailNum = Int16.Parse(dr["ACTIVE_FAIL"].ToString());

                // Kiểm tra tình trạng fail num
                // Nếu vượt quá hoặc đúng 5 lần trước đó thì không được truy cập nữa mà phải đợi
                if (iActiveFailNum >= 5)
                {
                    // Kiểm tra xem nếu như ngày hiện tại đã đủ thời gian lock
                    DataTable dtLockOver = dbContext.readATable(LOCK_DATE, CommandType.Text, objForm);
                    
                    
                    if (dtLockOver.Rows.Count <= 0) 
                    { 
                        isAccess = 2;
                    }
                    else
                    {
                        
                        dbContext.executeNonQuery(RESET, CommandType.Text, objForm);
                    }
                } 
                else
                {
                    string isActive = dr["ISACTIVE"].ToString();
        
                    // Sau khi việc check khóa thành công
                    // Tiến hành update mở khóa để sử dụng
                    if (isActive.Equals("False"))
                    {
                        dbContext.executeNonQuery(UPDATE_SUCCESS, CommandType.Text, objForm);
                    }

                    // Tự động thêm vào bảng
                    // Bắt đầu sử dụng
                    bool isInsertAccount = insertIntoUnitAccount(scModel.maDonVi);

                    if (!isInsertAccount)
                    {
                        isAccess = 4;
                    }

                }
            }
            else
            {
                // Kiểm tra lần kích hoạt không đúng
                int iActiveFailNum = Int16.Parse(dr["ACTIVE_FAIL"].ToString());

                // nếu vẫn trong phạm vi cho phép thì cộng thêm
                if (iActiveFailNum < 5)
                {
                    dbContext.executeNonQuery(UPDATE_FAIL, CommandType.Text, objForm);
                }
                else
                {
                    // nếu quá 5 lần tự động khóa luôn mã đơn vị và mã an toàn
                    // trong vòng 24 h mới được nhập lại
                    if (lockDate == null || lockDate == string.Empty)
                    {
                        dbContext.executeNonQuery(UPDATE_LOCK, CommandType.Text, objForm);
                    }
                    isAccess = 3;
                }
            }

            return isAccess;
        }

        /// <summary>
        /// Thêm 
        /// </summary>
        /// <param name="madonvi"></param>
        /// <returns></returns>
        private bool insertIntoUnitAccount(string madonvi)
        {
            DonViMaster master = getDonViInformation(madonvi);
            string[] arrColumn = { "UNIT_CODE", "SECURITY_PATTERN", "SERIAL_KEY", "PASSWORD", "FIRST_LOGIN", "INS_USER", "INS_DATE" };
            string[] arrParameter = { "@unitcode", "@securitypatern", "@serialkey", "@password", "@firstlogin", "@insuser", "@insdate" };
            SqlBuilderBasical sb = new SqlBuilderBasical(arrColumn, "HDVNACC.UNIT_ACCOUNT", arrParameter);
            string sql = sb.setInsertSQLStatement();

            if (sql == string.Empty)
            {
                return false;
            }

            Dictionary<string, object> objUnitAccount = new Dictionary<string, object>();
            DateTime dtCurrent = DateTime.Now;
            
            objUnitAccount.Add(arrParameter[0], master.MaDonVi);
            objUnitAccount.Add(arrParameter[1], EncryptDataAndDecryptData.Encrypt(scModel.securityCode, true,scModel.securityCode));
            objUnitAccount.Add(arrParameter[2], EncryptDataAndDecryptData.Encrypt(scModel.securityCode + "AA", true,scModel.securityCode + "AA"));
            objUnitAccount.Add(arrParameter[3], EncryptDataAndDecryptData.Encrypt(scModel.maDonVi, true, scModel.maDonVi));
            objUnitAccount.Add(arrParameter[4], dtCurrent);
            objUnitAccount.Add(arrParameter[5], master.MaDonVi);
            objUnitAccount.Add(arrParameter[6], dtCurrent);

            return dbContext.executeNonQuery(sql, CommandType.Text, objUnitAccount);

        }

        protected bool checkUnitExist(string madonvi)
        {
            return getDonViInformation(madonvi) != null;
        }

        /// <summary>
        /// Lấy Thông tin đơn vị
        /// </summary>
        /// <param name="madonvi"></param>
        /// <returns></returns>
        protected DonViMaster getDonViInformation(string madonvi)
        {
            Dictionary<string, object> obj = new Dictionary<string, object>();

            obj.Add("@madonvi", madonvi);

            DataTable dt = dbContext.readATable(GET_UNIT_INFORMATION, CommandType.Text, obj);

            if (dt == null || dt.Rows.Count == 0 )
            {
                return null;
            }

            DonViMaster donViMaster = new DonViMaster();

            donViMaster.MaDonVi = dt.Rows[0]["MA_DON_VI"].ToString();
            donViMaster.TenDonVi = dt.Rows[0]["TEN_DON_VI"].ToString();
            donViMaster.Email = dt.Rows[0]["EMAIL"].ToString();
            donViMaster.Email2 = dt.Rows[0]["EMAIL_2"].ToString();
            donViMaster.SoDienThoaiDd = dt.Rows[0]["SO_DIEN_THOAI_DD"].ToString();

            return donViMaster;
        }

        /// <summary>
        /// Kiểm tra giá trị đăng nhập
        /// </summary>
        /// <param name="securityModel"></param>
        /// <returns></returns>
        private int validateInput(SecurityModel securityModel)
        {
            if (securityModel.maDonVi.Length != 8)
            {
                return 10001;
            }

            if (securityModel.securityCode.Length != 16)
            {
                return 10002;
            }

            return 0;
        }
    }
}
